package cn.xeblog.plugin.tools.read.ui;

import javax.swing.*;
import javax.swing.text.*;

/**
 * 自动下一行文本面板
 *
 * @author LYF
 * @date 2022-06-24
 */
public class AutoNewlineTextPane extends JTextPane {

    /**
     * 构建面板
     */
    public AutoNewlineTextPane() {
        super();
        // 设置行为编辑器
        this.setEditorKit(new WarpEditorKit());
    }

    /**
     * 编辑器工具包（样式化文本，提供编辑样式化文本的最小操作集合）
     * <p>
     * 针对Bug  JTextPane中当输入较长的英文无空格时，会认为这是一个单词，并且自动换行失效，导致JTextPane的实际宽度变大出现滚动条,通过重写编辑器工具包来控制这个bug
     * </p>
     * <p>内部类---以下内部类全都用于实现自动强制折行</p>
     */
    private static class WarpEditorKit extends StyledEditorKit {
        /**
         * 默认的视图工厂
         */
        private final ViewFactory defaultFactory = new WarpColumnFactory();

        @Override
        public ViewFactory getViewFactory() {
            return defaultFactory;
        }
    }

    /**
     * 视图工厂，
     * <p>
     * 与StyledEditorKit#defaultFactory相比:
     * <pre>
     * public View create(Element elem) {
     *   ...
     *    if (kind.equals(AbstractDocument.ContentElementName)) {
     *      return new LabelView(elem);
     *   ...
     * }
     * </pre>
     * 只是针对AbstractDocument.ContentElementName重写了LabelView实现
     */
    private static class WarpColumnFactory implements ViewFactory {

        @Override
        public View create(Element elem) {
            String kind = elem.getName();
            if (kind != null) {
                if (kind.equals(AbstractDocument.ContentElementName)) {
                    // 内容
                    return new WarpLabelView(elem);
                } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
                    // 段落
                    return new ParagraphView(elem);
                } else if (kind.equals(AbstractDocument.SectionElementName)) {
                    // 节(行/段)
                    return new BoxView(elem, View.Y_AXIS);
                } else if (kind.equals(StyleConstants.ComponentElementName)) {
                    // 组件
                    return new ComponentView(elem);
                } else if (kind.equals(StyleConstants.IconElementName)) {
                    // 图标
                    return new IconView(elem);
                }
            }

            // default to text display
            return new LabelView(elem);
        }
    }

    /**
     * 重写LabelView，主要是重写LabelView#getMinimumSpan方法中的针对View.X_AXIS操作
     */
    private static class WarpLabelView extends LabelView {

        public WarpLabelView(Element elem) {
            super(elem);
        }

        @Override
        public float getMinimumSpan(int axis) {
            // 确定视图指定轴的最小宽度
            switch (axis) {
                case View.X_AXIS:
                    return 0;
                case View.Y_AXIS:
                    return super.getMinimumSpan(axis);
                default:
                    throw new IllegalArgumentException("Invalid axis: " + axis);
            }
        }
    }
}
